package cn.wjh.business.service.impl;

import cn.wjh.business.config.TLateConfig;
import cn.wjh.business.domain.vo.MailVo;
import cn.wjh.business.domain.vo.RegisterVo;
import cn.wjh.business.service.ILoginService;
import cn.wjh.business.service.IMailService;
import cn.wjh.common.constant.Constants;
import cn.wjh.common.core.domain.entity.SysUser;
import cn.wjh.common.core.domain.model.LoginUser;
import cn.wjh.common.core.redis.RedisCache;
import cn.wjh.common.enums.UserStatus;
import cn.wjh.common.exception.ServiceException;
import cn.wjh.common.utils.DateUtils;
import cn.wjh.common.utils.MessageUtils;
import cn.wjh.common.utils.SecurityUtils;
import cn.wjh.common.utils.StringUtils;
import cn.wjh.common.utils.ip.IpUtils;
import cn.wjh.framework.manager.AsyncManager;
import cn.wjh.framework.manager.factory.AsyncFactory;
import cn.wjh.framework.web.service.SysPermissionService;
import cn.wjh.framework.web.service.TokenService;
import cn.wjh.system.mapper.SysUserMapper;
import cn.wjh.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
@Slf4j
public class LoginServiceImpl implements ILoginService {
    @Resource
    private IMailService mailService;

    @Resource
    private ISysUserService userService;

    @Resource
    private SysPermissionService permissionService;
    @Resource
    private RedisCache redisCache;

    @Resource
    private TokenService tokenService;

    @Resource
    private TLateConfig config;


    @Override
    public String mailLogin(MailVo mailVo) {
        if (!mailService.verifyCode(mailVo)) throw new ServiceException("邮箱验证码错误!", 400);
        /*获取用户信息*/
        SysUser user = userService.selectUserByEmail(mailVo.getEmail());

        if (StringUtils.isNull(user)) throw new ServiceException("用户不存在!");

        LoginUser loginUser = (LoginUser) validateUser(user);//检验用户
        recordLoginInfo(user.getUserId());//记录用户登录

        String code_key = mailVo.getTitle().concat(":" + mailVo.getEmail()).concat(":code");//邮箱验证码存储key title:to:code
        redisCache.deleteObject(code_key);//删除验证码


        AsyncManager.me().execute(AsyncFactory.recordLogininfor(user.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));


        //生成令牌
        return tokenService.createToken(loginUser);
    }

    /**
     * 邮箱注册并登录
     *
     * @param registerVo
     * @return
     */
    @Override
    public String mailRegister(RegisterVo registerVo) {
        if (!mailService.verifyCode(registerVo)) throw new ServiceException("邮箱验证码错误!", 400);
        SysUser user = generateUser(registerVo);//生成用户
        if (StringUtils.isNull(user)) throw new ServiceException("注册失败!请重试!");


        LoginUser loginUser = (LoginUser) createLoginUser(user);//创建登录用户
        recordLoginInfo(user.getUserId());//记录用户登录

        String code_key = registerVo.getTitle().concat(":" + registerVo.getEmail()).concat(":code");//邮箱验证码存储key title:to:code
        redisCache.deleteObject(code_key);//删除验证码

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(user.getUserName(), Constants.REGISTER, MessageUtils.message("user.register.success")));

        //生成令牌
        return tokenService.createToken(loginUser);
    }

    /**
     * 生成用户 6-10位用户名
     *
     * @return
     */
    private SysUser generateUser(RegisterVo registerVo) {
        try {
            SysUser user = new SysUser();
            String email = registerVo.getEmail();//邮箱
            user.setUserName(email);//用户名
            user.setNickName(email);//昵称
            user.setPassword(SecurityUtils.encryptPassword(registerVo.getPassword()));//密码
            user.setEmail(email);//邮箱
            user.setDeptId(config.getDefaultDeptId());//默认部门
            user.setRoleIds(new Long[]{config.getDefaultRoleId()});//默认角色
            userService.insertUser(user);
            return userService.selectUserByUserName(email);//查找出完整的用户
        } catch (DuplicateKeyException e) {
            throw new ServiceException("邮箱已被注册！", 400);
        }
    }

    /*检验用户*/
    private UserDetails validateUser(SysUser user) {
        verifyLoginUser(user, user.getUserName());
        return createLoginUser(user);
    }

    /*创建登录用户信息*/
    private UserDetails createLoginUser(SysUser user) {
        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
    }

    private static void verifyLoginUser(SysUser user, String username) {
        if (StringUtils.isNull(user)) {
            log.info("登录用户：{} 不存在.", username);
            throw new ServiceException(MessageUtils.message("user.not.exists"));
        } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            log.info("登录用户：{} 已被删除.", username);
            throw new ServiceException(MessageUtils.message("user.password.delete"));
        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            log.info("登录用户：{} 已被停用.", username);
            throw new ServiceException(MessageUtils.message("user.blocked"));
        }
    }

    /**
     * 记录登录信息
     *
     * @param userId
     */
    private void recordLoginInfo(Long userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }


}
